home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / CUJ9204.ARJ / 1004060A < prev    next >
Text File  |  1992-06-02  |  9KB  |  326 lines

  1. /* @(#) money.h          Copymiddle 1991 Adolfo Di Mare  */
  2. /*                                                       */
  3. /*            Yet Another Money C++ Class                */
  4. /*                                                       */
  5. /*   Use freely but acknowledge author and publication.  */
  6. /*    DO NOT SELL IT. The author reserves all rigths!    */
  7.  
  8. /*                               BITNET: adimare@UCRVM2  */
  9.  
  10. /* Compiler:                           Borland C++ v 2.0 */
  11. /*                          [should work with Turbo C++] */
  12.  
  13.  
  14. #ifndef _money_h
  15. #define _money_h
  16.  
  17. extern "C" {     // avoid type clashes with the C library
  18.     #include <math.h>    /* floor() */
  19.     #include <float.h>   /* DBL_DIG */
  20. }
  21.  
  22. #ifndef MONEY_DECIMALS       /* number of decimals in */
  23. #define MONEY_DECIMALS  2    /*   any money quantity  */
  24. #endif                       /* don't use parentesis! */
  25.  
  26. #define __VAL(n)  n               /* 1 level indirection */
  27. #define TENPOW(n) __VAL(1.0e##n)  /* Trick to yield 10^n */
  28.  
  29.  
  30. #define MONEY_DIG   DBL_DIG
  31.  
  32.  
  33. class money {
  34. public:
  35.  
  36.     static int    decimals() { return MONEY_DECIMALS;     }
  37.     static int    digits()   { return MONEY_DIG; }
  38.     static double SCALE()
  39.         { return TENPOW(MONEY_DECIMALS); }
  40.  
  41.     money();              // do nothing constructor
  42.     money(double);        // constructor from double
  43.     money(const money&);  // copy constructor
  44.  
  45.     money& operator= (const money&);  // copy operator
  46.     money& operator= (double);        // copy from double
  47.     operator double() const;          // convert to double
  48.  
  49.     int  OK()   const;  // check money's invariant
  50.     void FIX();         // get rid of unwanted decimals
  51.  
  52.  
  53.     friend money  operator + (const money&, const money&);
  54.     friend money  operator + (double,       const money&);
  55.     friend money  operator + (const money&, double);
  56.     friend money  operator - (const money&, const money&);
  57.     friend money  operator - (double,       const money&);
  58.     friend money  operator - (const money&, double);
  59.  
  60.     friend money  operator*  (const money&, double);
  61.     friend money  operator*  (double,       const money&);
  62.     friend double operator/  (const money&, const money&);
  63.     friend money  operator/  (const money&, double);
  64.     friend money  operator%  (const money&, const money&);
  65.  
  66.     // money  * money  is NOT valid
  67.     // double / money  is INVALID
  68.  
  69.     friend int operator == (const money&, const money&);
  70.     friend int operator != (const money&, const money&);
  71.     friend int operator <  (const money&, const money&);
  72.     friend int operator >  (const money&, const money&);
  73.     friend int operator <= (const money&, const money&);
  74.     friend int operator >= (const money&, const money&);
  75.  
  76.     money& operator += (const money&);
  77.     money& operator += (double);
  78.     money& operator -= (const money&);
  79.     money& operator -= (double);
  80.  
  81.     money& operator *= (double);
  82.     money& operator /= (double);
  83.  
  84.     friend money  operator+ (const money&);
  85.     friend money  operator- (const money&);
  86.     money& operator++();
  87.     money& operator--();
  88.     friend int    operator! (const money&);
  89.  
  90.     friend money abs(const money&);
  91.     friend money flatten(
  92.          const money& m,
  93.          double cents=0.25, int rounding = 1 /* TRUE */);
  94.  
  95. protected:         // let users change the class behaviour
  96.     double m_money;
  97. };
  98.  
  99. // Constructors && assignment
  100. inline money::money() {
  101. // do nothing constructor, for efficiency
  102. }
  103. inline money::money(double d) {
  104. // construct from double
  105.     m_money = d*SCALE();
  106.     FIX();
  107. }
  108. inline money::money(const money& m) {
  109. // copy constructor
  110.     m_money = m.m_money;
  111. }
  112.  
  113. inline money& money::operator= (const money& m) {
  114. // copy operator
  115.     m_money = m.m_money;
  116.     return *this;
  117. }
  118. inline money& money::operator= (double d) {
  119. // assign from double
  120.     m_money = d*SCALE();
  121.     FIX();
  122.     return *this;
  123. }
  124. inline money::operator double() const {
  125. // convert to double
  126.     return m_money / SCALE();
  127. }
  128.  
  129. inline int money::OK() const {
  130. // Returns TRUE (1) when the quantity stored
  131. // in *this really corresponds to a money
  132. // quantity.
  133.  
  134.     money temp;
  135.     temp.m_money = m_money;
  136.     temp.FIX();
  137.     return (
  138.         ( temp.m_money == m_money )
  139.           &&
  140.         ( fabs(m_money) < (TENPOW(DBL_DIG) / SCALE()) )
  141.     );
  142. }
  143.  
  144. inline void money::FIX() {
  145. // Deletes all decimals digits beyond
  146. // the MONEY_DECIMALS decimal place.
  147. // - If the value is out of range, FIX
  148. //   won't fix it.
  149.     m_money =
  150.         (m_money > 0.0
  151.             ?
  152.                 floor(
  153.                     m_money
  154.                      #ifdef MONEY_ROUNDING
  155.                         + 0.5 // 0.49 is also an option...
  156.                      #endif
  157.                  )
  158.             :
  159.                 ceil(
  160.                     m_money
  161.                      #ifdef MONEY_ROUNDING
  162.                         - 0.5
  163.                      #endif
  164.                  )
  165.         );
  166. }
  167.  
  168. // add
  169. inline money operator+ (const money& m, const money& mm) {
  170.     money temp;    // don't mult*SCALE()
  171.     temp.m_money = m.m_money + mm.m_money;
  172.     return temp;
  173. }
  174. inline money operator+ (double d, const money& m) {
  175.     return (money(d)+m);
  176. }
  177. inline money operator+ (const money& m, double d) {
  178.     return (m+money(d));
  179. }
  180.  
  181. // substract
  182. inline money operator- (const money& m, const money& mm) {
  183.     money temp;
  184.     temp.m_money = m.m_money - mm.m_money;
  185.     return temp;
  186. }
  187. inline money operator- (double d, const money& m) {
  188.     return (money(d)-m);
  189. }
  190. inline money operator- (const money& m, double d) {
  191.     return (m-money(d));
  192. }
  193.  
  194. // multiply
  195. inline money operator* (const money& m, double d) {
  196.     money temp;
  197.     temp.m_money = m.m_money * d; // don't mult by SCALE()
  198.     temp.FIX();    // this could be delayed...
  199.     return temp;
  200. }
  201. inline money operator* (double d, const money& m) {
  202.     return (m*d);
  203. }
  204.  
  205. // divide
  206. inline double operator/ (const money& m, const money& mm) {
  207.     return m.m_money / mm.m_money;
  208. }
  209. inline money  operator/ (const money& m, double d) {
  210.     money temp;
  211.     temp.m_money = m.m_money / d;
  212.     temp.FIX();    // this could be delayed...
  213.     return temp;
  214. }
  215. inline money operator%  (const money& m, const money& mm) {
  216.     money temp;
  217.     temp.m_money = fmod(m.m_money, mm.m_money);
  218.     temp.FIX();    // this could be delayed...
  219.     return temp;
  220. }
  221.  
  222. // compare
  223. inline int operator  == (const money& m, const money& mm) {
  224.     return m.m_money ==  mm.m_money;
  225. }
  226. inline int operator  != (const money& m, const money& mm) {
  227.     return m.m_money !=  mm.m_money;
  228. }
  229. inline int operator  <  (const money& m, const money& mm) {
  230.     return m.m_money <   mm.m_money;
  231. }
  232. inline int operator  >  (const money& m, const money& mm) {
  233.     return m.m_money >   mm.m_money;
  234. }
  235. inline int operator  <= (const money& m, const money& mm) {
  236.     return m.m_money <=  mm.m_money;
  237. }
  238. inline int operator  >= (const money& m, const money& mm) {
  239.     return m.m_money >=  mm.m_money;
  240. }
  241.  
  242. inline money& money::operator += (const money& m) {
  243.     m_money += m.m_money;
  244.     return *this;
  245. }
  246. inline money& money::operator += (double d) {
  247.     m_money += d*SCALE();
  248.     FIX();
  249.     return *this;
  250. }
  251. inline money& money::operator -= (const money& m) {
  252.     m_money -= m.m_money;
  253.     return *this;
  254. }
  255. inline money& money::operator -= (double d) {
  256.     m_money -= d*SCALE();
  257.     FIX();
  258.     return *this;
  259. }
  260. inline money& money::operator *= (double d) {
  261.     m_money *= d;
  262.     FIX();
  263.     return *this;
  264. }
  265. inline money& money::operator /= (double d) {
  266.     m_money /= d;
  267.     FIX();
  268.     return *this;
  269. }
  270.  
  271. // unary op's
  272. inline money operator+(const money& m) {
  273.     return m;
  274. }
  275. inline money operator-(const money& m) {
  276.     money temp;
  277.     temp.m_money = -m.m_money;
  278.     return temp;
  279. }
  280. inline money& money::operator++() {
  281.     m_money += SCALE();
  282.     #if (MONEY_DECIMALS<0)
  283.         FIX(); // avoid problems because of
  284.     #endif     // the representation of 10^-n
  285.     return *this;
  286. }
  287. inline money& money::operator--() {
  288.     m_money -= SCALE();
  289.     #if (MONEY_DECIMALS<0)
  290.         FIX();
  291.     #endif
  292.     return *this;
  293. }
  294. inline int operator!(const money& m) {
  295.     return m.m_money == 0.0;
  296. }
  297.  
  298. inline money abs(const money& m) {
  299.     money temp;
  300.     temp.m_money = fabs(m.m_money);
  301.     return temp;
  302. }
  303.  
  304. money flatten(const money& m, double cents, int rounding) {
  305. // Returns a money data item where the cents are
  306. // rounded modulo "cents". In this way cents can
  307. // be stripped of money items when the currency
  308. // does not have all the coins required to pay
  309. // every posible quantity.
  310.     money temp;
  311.     double c = floor(fabs(cents*money::SCALE())); // cents
  312.     double r = fmod(m.m_money, c);            // remainder
  313.     temp.m_money =
  314.         (!rounding || (2.0* r <= c)
  315.             ? m.m_money - r
  316.             : m.m_money - r + c
  317.         );
  318.     return temp;
  319. }
  320.  
  321. /* Avoid name space overcrowding */
  322. #undef __VAL
  323. #undef TENPOW /* jic: Just In Case! */
  324.  
  325. #endif  /* _money_h */
  326.